// This is the main DLL file.

#include "stdafx.h"

#include "NativeLexer.h"
#include "parser.h"
#include <vcclr.h>
#include <string>

namespace Tycho {
namespace Lexer {

	char *clrStringToUtf8String (System::String ^clrString) {
		size_t mbSize;

		pin_ptr<const wchar_t> wideChars = PtrToStringChars (clrString);

		wcstombs_s (&mbSize, NULL, 0, wideChars, clrString->Length);
		char *utf8String = new char [mbSize];
		wcstombs_s (&mbSize, utf8String, mbSize, wideChars, clrString->Length);

		return utf8String;
	}

	System::Collections::Generic::List<Tycho::Parser::Tokens::Token^> ^NativeLexer::Lex (System::String ^code) {
		return Lex (code, nullptr);
	}

	System::Collections::Generic::List<Tycho::Parser::Tokens::Token^> ^NativeLexer::Lex (System::String ^code, System::String ^fileName) {
		Block block;

		block.consume (clrStringToUtf8String (code));
		block._source = clrStringToUtf8String (code);
		if (fileName != nullptr) {
			block._file_name = clrStringToUtf8String (fileName);
		}

		::Parser parser;
		block.lex (&parser);

		ListToken *list_token = parser.get_list_token (ListToken::List);
		
		System::Collections::Generic::List<Tycho::Parser::Tokens::Token^> ^tokens = list_token->to_clr_tokens ();

		delete list_token;

		return tokens;
	}

	System::Collections::Generic::List<Tycho::Parser::Tokens::Token^> ^NativeLexer::InterpolateString (System::String ^string, Tycho::Parser::Tokens::SourceLocation ^sloc) {
		Block block;

		block.consume (clrStringToUtf8String (string));
		block._source = clrStringToUtf8String (string);
		if (sloc->FileName != nullptr) {
			block._file_name = clrStringToUtf8String (sloc->FileName);
		}
		block._lineno = sloc->LineStart;
		block._colno = sloc->ColumnStart;

		::Lexer lex (&block);

		vector<Token*> tokens;
		lex.interpolate (&tokens);

		System::Collections::Generic::List<Tycho::Parser::Tokens::Token^> ^tokenList = gcnew System::Collections::Generic::List<Tycho::Parser::Tokens::Token^> ();
		for (vector<Token*>::iterator i = tokens.begin (); i != tokens.end (); i++) {
			tokenList->Add ((*i)->to_clr ());
		}

		return tokenList;
	}

}
}